#include "Test.h"
#include "SymtableV0.h"
#include "ScannerImpl.h"
#include "ScannerV0.h"
#include "Buffer.h"
#include <assert.h>
#include "Helper.h"
#include "TokenPrinter.h"
#include <iostream>



Test::Test(void)
{
}


Test::~Test(void)
{
}

void Test::testSymtab()
{
}

void Test::testHelper()
{
    assert(Helper::isNumerical('0'));
    assert(Helper::isNumerical('1'));
    assert(Helper::isNumerical('2'));
    assert(Helper::isNumerical('3'));
    assert(Helper::isNumerical('4'));
    assert(Helper::isNumerical('5'));
    assert(Helper::isNumerical('6'));
    assert(Helper::isNumerical('7'));
    assert(Helper::isNumerical('8'));
    assert(Helper::isNumerical('9'));

    assert(!Helper::isNumerical('a'));
    assert(!Helper::isNumerical('z'));
    assert(!Helper::isNumerical('A'));
    assert(!Helper::isNumerical('Z'));
    
    assert(Helper::isAlpha('a'));
    assert(Helper::isAlpha('z'));
    assert(Helper::isAlpha('A'));
    assert(Helper::isAlpha('Z'));

    assert(!Helper::isAlpha('0'));
    assert(!Helper::isAlpha('1'));
    assert(!Helper::isAlpha('2'));
    assert(!Helper::isAlpha('3'));
    assert(!Helper::isAlpha('4'));
    assert(!Helper::isAlpha('5'));
    assert(!Helper::isAlpha('6'));
    assert(!Helper::isAlpha('7'));
    assert(!Helper::isAlpha('8'));
    assert(!Helper::isAlpha('9'));

    assert(Helper::isSign('+'));
    assert(Helper::isSign('-'));
    assert(Helper::isSign('/'));
    assert(Helper::isSign('*'));
    assert(Helper::isSign('<'));
    assert(Helper::isSign('>'));
    assert(Helper::isSign('='));
    //assert(Helper::isSign('<!>'));
    assert(Helper::isSign('!'));
    assert(Helper::isSign('&'));
    assert(Helper::isSign(';'));
    assert(Helper::isSign('('));
    assert(Helper::isSign(')'));
    assert(Helper::isSign('{'));
    assert(Helper::isSign('}'));
    assert(Helper::isSign('['));
    assert(Helper::isSign(']'));

    assert(!Helper::isSign('"'));
    assert(!Helper::isSign('s'));
    assert(!Helper::isSign('$'));
    assert(!Helper::isSign('%'));
    assert(!Helper::isSign('?'));
    assert(!Helper::isSign('a'));
    assert(!Helper::isSign('A'));
    assert(!Helper::isSign('z'));
    assert(!Helper::isSign('Z'));
    assert(!Helper::isSign('0'));
    assert(!Helper::isSign('9'));
}


void Test::testBuffer(){
    printf("Test::testBuffer():");
char sa;
	// Testen von getchar() und putchar()
	// README enthält 65000 Zeichen
	// sobald man EOF zurück kriegt wird Test abgeschlossen.
	// Für readme muss man Direckten Pfad angeben
	Buffer test((char*) "README",(char*) "output");
	for (int i = 0; i < 100000; i++) {
		sa=test.getchar();
		if(sa==EOF){
			test.close();
			break;
		}
		test.putchar(sa);
	}
	// Testen von Puffergrenzen mit ungetchar();
	Buffer test1((char*) "README",(char*) "output1");
		for (int i = 0; i < 4070; i++) {
			sa=test1.getchar();
			}
	test1.putchar(sa);
	std::cout<<"***"<<sa<<"***"<<std::endl;
	for(int i=0; i<30; i++){
		sa=test1.getchar();
	}
	test1.ungetchar(31);
	sa=test1.getchar();
	test1.putchar(sa);
	std::cout<<"***"<<sa<<"***"<<std::endl;
	test1.close();
	Buffer test2((char*) "/home/arturblack/workspace/Buffer/src/README",(char*) "output2");
			for (int i = 0; i < 9900; i++) {
				sa=test2.getchar();
				}
		test2.putchar(sa);
		std::cout<<"***"<<sa<<"***"<<std::endl;
		for(int i=0; i<100; i++){
			sa=test2.getchar();
		}
		test2.ungetchar(101);
		sa=test2.getchar();
		test2.putchar(sa);
		std::cout<<"***"<<sa<<"***"<<std::endl;
		test2.close();
    printf("\n");
}


void Test::testState2()
{
    printf("testState2():");
    ScannerV0* scanner = new ScannerImpl("Test_Integer.txt");
    assert(scanner->nextToken()->getInt() == 238);
    assert(scanner->nextToken()->getInt() == 2398);
    assert(scanner->nextToken()->getInt() == 12);
    assert(scanner->nextToken()->getInt() == MAX_INT);
    assert(scanner->nextToken()->getInt() == 2893);
    assert(scanner->nextToken()->getInt() == 2342425);
    assert(scanner->nextToken()->getInt() == 32323);
    assert(scanner->nextToken()->getInt() == 0);
    assert(scanner->nextToken()->getInt() == 11);
    assert(scanner->nextToken()->getInt() == 0);
    assert(scanner->nextToken()->getInt() == 12);
    assert(scanner->nextToken()->getInt() == 1);
    assert(scanner->nextToken()->getInt() == 20000);
    printf("\n");
}

void Test::testState3()
{
    printf("testState3():");
    ScannerV0* scanner = new ScannerImpl("Test_Identifier.txt");
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "das") == 0);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "ist") == 0);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "ein") == 0);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "test") == 0);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "hahaha") == 0);
    printf("\n");
}

void Test::testState111213()
{
    printf("testState111213():");
    ScannerV0* scanner = new ScannerImpl("Test_Special.txt"); //+-*<><!><!<+
    assert(scanner->nextToken()->getChar() == '+');
    assert(scanner->nextToken()->getChar() == '-');
    assert(scanner->nextToken()->getChar() == '*');
    assert(scanner->nextToken()->getChar() == '<');
    assert(scanner->nextToken()->getChar() == '>');
    assert(scanner->nextToken()->getType() == TOK_SPECIAL);
    assert(scanner->nextToken()->getChar() == '<');
    assert(scanner->nextToken()->getChar() == '!');
    assert(scanner->nextToken()->getChar() == '<');
    assert(scanner->nextToken()->getChar() == '+');
    printf("\n");
}

void Test::testState414243()
{
    printf("testState414243():");
    ScannerV0* scanner = new ScannerImpl("Test_Comment.txt");
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "das") == 0);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "ist") == 0);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "ein") == 0);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "test") == 0);
    assert(scanner->nextToken()->getInt() == 238);
    assert(scanner->nextToken()->getInt() == 2398);
    assert(strcmp(scanner->lookup(scanner->nextToken()->getKey()).lexem, "hahaha") == 0);
    assert(scanner->nextToken()->getInt() == 12);
    assert(scanner->nextToken()->getInt() == MAX_INT);
    assert(scanner->nextToken()->getInt() == 2893);
    assert(scanner->nextToken()->getInt() == 2342425);
    assert(scanner->nextToken()->getInt() == 32323);
    assert(scanner->nextToken()->getInt() == 0);
    assert(scanner->nextToken()->getInt() == 11);
    //assert(scanner->nextToken()->getType() == TOK_COMMENT_OPEN);
    //assert(scanner->nextToken()->getType() == TOK_COMMENT_CLOSE);
    assert(scanner->nextToken()->getChar() == '*');
    assert(scanner->nextToken()->getChar() == '/');
    assert(scanner->nextToken()->getInt() == 0);
    //assert(scanner->nextToken()->getType() == TOK_COMMENT_OPEN);
    //assert(scanner->nextToken()->getType() == TOK_COMMENT_CLOSE);
    assert(scanner->nextToken()->getInt() == 1);
    assert(scanner->nextToken()->getInt() == 20000);
    assert(scanner->nextToken()->getChar() == '+');
    assert(scanner->nextToken()->getChar() == '-');
    //assert(scanner->nextToken()->getType() == TOK_COMMENT_OPEN);
    //assert(scanner->nextToken()->getType() == TOK_COMMENT_CLOSE);
    assert(scanner->nextToken()->getChar() == '<');
    assert(scanner->nextToken()->getChar() == '!');
    assert(scanner->nextToken()->getChar() == '<');
    assert(scanner->nextToken()->getChar() == '+');
    printf("\n");
}

void Test::testStates()
{
    Test::testState2();
    Test::testState3();
    Test::testState111213();
    Test::testState414243();
}

void Test::test()
{
    Test::testSymtab();
    Test::testHelper();
    Test::testStates();
    Test::testBuffer();
}

int main(int argc, char ** argv) 
{
    if(argc < 2){
         Test::test();
         return 0;
    }
    ScannerV0* scanner = new ScannerImpl(argv[1]);

    Token* t = NULL;
    int tokenNr = 0;

    while ((t = scanner->nextToken()) != NULL) {
        //for debugging:
        //printf("Token #%d\n", ++tokenNr);
        TokenPrinter::printToken(stdout, t, scanner);
    }

    return 0;
}
